﻿using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using YiSha.SqlSugars;

namespace YiSha.SqlSugars
{
    /// <summary>
    /// Sugar ORM父类, 封装一些基本的操作
    /// </summary>
    public static class SugarBase
    {
        /// <summary>
        /// 数据库链接字符串
        /// </summary>
        public static string DB_ConnectionString { get; set; }
        /// <summary>
        /// 数据库类型
        /// </summary>
        public static SqlSugar.DbType DbType { get; set; }
        /// <summary>
        /// 数据库连接类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dbType"></param>
        /// <returns></returns>
        public static SqlSugarClient GetInstance<T>()
        {
            return SugarBase.GetInstance(30);
        }
        /// <summary>
        /// 获得SqlSugarClient(使用该方法, 默认请手动释放资源, 如using(var db = SugarBase.GetIntance()){你的代码}, 如果把isAutoCloseConnection参数设置为true, 则无需手动释放, 会每次操作数据库释放一次, 可能会影响性能, 请自行判断使用)
        /// </summary>
        /// <param name="commandTimeOut">等待超时时间, 默认为30秒 (单位: 秒)</param>
        /// <returns></returns>
        public static SqlSugarClient GetInstance(int commandTimeOut = 30)
        {
            return SugarBase.InitDB(commandTimeOut);
        }

        /// <summary>
        /// 初始化ORM连接对象
        /// </summary>
        /// <param name="commandTimeOut">等待超时时间, 默认为30秒 (单位: 秒)</param>
        public static SqlSugarClient InitDB(int commandTimeOut = 30)
        {
            var db = new SqlSugarClient(new ConnectionConfig()
            {
                ConnectionString = DB_ConnectionString,
                DbType = DbType,
                IsAutoCloseConnection = true,
                InitKeyType = InitKeyType.SystemTable,
                ConfigureExternalServices = new ConfigureExternalServices()
                {
                    DataInfoCacheService = new SugarCache() //配置我们创建的缓存类
                }
            });
            db.Ado.CommandTimeOut = commandTimeOut;
            db.Ado.IsEnableLogEvent = true;
            //SQL执行完事件
            db.Aop.OnLogExecuted = (sql, pars) =>
            {
                Console.WriteLine("=========SQL执行完事件开始===========");
                Console.WriteLine(DateTime.Now);
                Console.WriteLine("starting:" + sql + " " + pars);
                Console.WriteLine("=========SQL执行完事件结束==========");
            };
            //SQL执行前事件
            db.Aop.OnLogExecuting = (sql, pars) =>
            {

            };
            //执行SQL 错误事件
            db.Aop.OnError = (exp) =>
            {
                //exp.sql exp.parameters 可以拿到参数和错误Sql     
                Console.WriteLine("=========执行SQL 错误事件开始===========");
                Console.WriteLine(DateTime.Now);
                Console.WriteLine("starting:" + exp.Sql + " " + exp.Parametres);
                Console.WriteLine("错误信息:" + exp.Message);
                Console.WriteLine("=========执行SQL 错误事件结束==========");
            };
            //SQL执行前 可以修改SQL
            db.Aop.OnExecutingChangeSql = (sql, pars) =>
            {
                return new KeyValuePair<string, SugarParameter[]>(sql, pars);
            };
            return db;
        }

        /// <summary>
        /// 执行数据库操作
        /// </summary>
        /// <typeparam name="Result">返回值类型 泛型</typeparam>
        /// <param name="func">方法委托</param>
        /// <param name="commandTimeOut">超时时间, 单位为秒, 默认为30秒</param>
        /// <param name="dbType">数据库类型, 默认为SQL Server</param>
        /// <returns>泛型返回值</returns>
        public static Result Exec<Result>(Func<SqlSugarClient, Result> func, int commandTimeOut = 30)
        {
            if (func == null)
            {
                throw new Exception("委托为null, 事务处理无意义");
            }
            Result result;
            using (SqlSugarClient sqlSugarClient = SugarBase.InitDB(commandTimeOut))
            {
                try
                {
                    result = func(sqlSugarClient);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    sqlSugarClient.Dispose();
                }
            }
            return result;
        }

        /// <summary>
        /// 带事务处理的执行数据库操作
        /// </summary>
        /// <typeparam name="Result">返回值类型 泛型</typeparam>
        /// <param name="func">方法委托</param>
        /// <param name="commandTimeOut">超时时间, 单位为秒, 默认为30秒</param>
        /// <param name="dbType">数据库类型, 默认为SQL Server</param>
        /// <returns>泛型返回值</returns>
        public static Result ExecTran<Result>(Func<SqlSugarClient, Result> func, int commandTimeOut = 30)
        {
            if (func == null)
            {
                throw new Exception("委托为null, 事务处理无意义");
            }
            Result result2;
            using (SqlSugarClient sqlSugarClient = SugarBase.InitDB(commandTimeOut))
            {
                try
                {
                    sqlSugarClient.Ado.BeginTran(IsolationLevel.Unspecified);
                    Result result = func(sqlSugarClient);
                    sqlSugarClient.CommitTran();
                    result2 = result;
                }
                catch (Exception ex)
                {
                    sqlSugarClient.RollbackTran();
                    throw ex;
                }
                finally
                {
                    sqlSugarClient.Dispose();
                }
            }
            return result2;
        }
    }
}
